package com.hhf.springboot.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hhf.springboot.common.ChartDataItem;
import com.hhf.springboot.common.DataGroupByDateDTO;
import com.hhf.springboot.common.ErrorCode;
import com.hhf.springboot.mapper.OrderInfoMapper;
import com.hhf.springboot.model.dto.bisheProject.BisheProjectClickDTO;
import com.hhf.springboot.constant.CommonConstant;
import com.hhf.springboot.exception.BusinessException;
import com.hhf.springboot.exception.ThrowUtils;
import com.hhf.springboot.mapper.BisheProjectMapper;
import com.hhf.springboot.model.dto.bisheProject.BisheProjectQueryRequest;
import com.hhf.springboot.model.dto.bisheProject.BisheProjectStatisticsDTO;
import com.hhf.springboot.model.entity.BisheProject;
import com.hhf.springboot.model.entity.OrderInfo;
import com.hhf.springboot.model.entity.User;
import com.hhf.springboot.model.enums.OrderInfoStatusEnum;
import com.hhf.springboot.model.enums.OrderInfoTypeEnum;
import com.hhf.springboot.model.vo.BisheProjectVO;
import com.hhf.springboot.model.vo.UserVO;
import com.hhf.springboot.model.vo.WordCloud;
import com.hhf.springboot.service.BisheProjectService;
import com.hhf.springboot.service.UserService;
import com.hhf.springboot.utils.DateUtils;
import com.hhf.springboot.utils.SqlUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 毕设项目服务实现
 *
 * @author hhf
 * @from <a href="https://gitee.com/hanhuaifei/projects">我的gitee</a>
 * @Date 2024/9/26
 */
@Service
@Slf4j
public class BisheProjectServiceImpl extends ServiceImpl<BisheProjectMapper, BisheProject> implements BisheProjectService {

    @Resource
    private UserService userService;


    @Resource
    private OrderInfoMapper orderInfoMapper;

    /**
     * 校验数据
     *
     * @param bisheProject
     * @param add          对创建的数据进行校验
     */
    @Override
    public void validBisheProject(BisheProject bisheProject, boolean add) {
        ThrowUtils.throwIf(bisheProject == null, ErrorCode.PARAMS_ERROR);
        // 从对象中取值
        String title = bisheProject.getTitle();
        String subtitle = bisheProject.getSubtitle();
        String introduce = bisheProject.getIntroduce();

        // 创建数据时，参数不能为空
        if (add) {
            // 补充校验规则
            ThrowUtils.throwIf(StringUtils.isBlank(title), ErrorCode.PARAMS_ERROR);
            ThrowUtils.throwIf(StringUtils.isBlank(subtitle), ErrorCode.PARAMS_ERROR);
            ThrowUtils.throwIf(StringUtils.isBlank(introduce), ErrorCode.PARAMS_ERROR);
        }
        // 修改数据时，有参数则校验
        // 补充校验规则
        if (StringUtils.isNotBlank(title)) {
            ThrowUtils.throwIf(title.length() > 80, ErrorCode.PARAMS_ERROR, "标题过长");
        }
        if (StringUtils.isNotBlank(subtitle)) {
            ThrowUtils.throwIf(title.length() > 80, ErrorCode.PARAMS_ERROR, "子标题过长");
        }
    }

    /**
     * 获取查询条件
     *
     * @param bisheProjectQueryRequest
     * @return
     */
    @Override
    public QueryWrapper<BisheProject> getQueryWrapper(BisheProjectQueryRequest bisheProjectQueryRequest) {
        QueryWrapper<BisheProject> queryWrapper = new QueryWrapper<>();
        if (bisheProjectQueryRequest == null) {
            return queryWrapper;
        }
        Long id = bisheProjectQueryRequest.getId();
        String title = bisheProjectQueryRequest.getTitle();
        Integer status = bisheProjectQueryRequest.getStatus();
        List<String> tagList = bisheProjectQueryRequest.getTagList();
        Long userId = bisheProjectQueryRequest.getUserId();
        String sortField = bisheProjectQueryRequest.getSortField();
        String sortOrder = bisheProjectQueryRequest.getSortOrder();

        // 补充需要的查询条件
        // 模糊查询
        queryWrapper.like(StringUtils.isNotBlank(title), "title", title);
        // JSON 数组查询
        if (CollUtil.isNotEmpty(tagList)) {
            for (String tag : tagList) {
                queryWrapper.like("tags", "\"" + tag + "\"");
            }
        }

        // 精确查询
        queryWrapper.eq(ObjectUtils.isNotEmpty(id), "id", id);
        queryWrapper.eq(ObjectUtils.isNotEmpty(userId), "user_id", userId);
        queryWrapper.eq(ObjectUtils.isNotEmpty(status), "status", status);

        // 排序规则
        queryWrapper.orderBy(SqlUtils.validSortField(sortField),
                sortOrder.equals(CommonConstant.SORT_ORDER_ASC),
                StrUtil.toUnderlineCase(sortField));

        return queryWrapper;
    }

    /**
     * 获取毕设项目封装
     *
     * @param bisheProject
     * @param request
     * @return
     */
    @Override
    public BisheProjectVO getBisheProjectVO(BisheProject bisheProject, HttpServletRequest request) {
        // 对象转封装类
        BisheProjectVO bisheProjectVO = BisheProjectVO.objToVo(bisheProject);

        // 可以根据需要为封装对象补充值，不需要的内容可以删除
        // region 可选
        // 1. 关联查询用户信息
        Long userId = bisheProject.getUserId();
        User user = null;
        if (userId != null && userId > 0) {
            user = userService.getById(userId);
        }
        UserVO userVO = userService.getUserVO(user);
        bisheProjectVO.setUser(userVO);
        // endregion

        return bisheProjectVO;
    }

    /**
     * 分页获取毕设项目封装
     *
     * @param bisheProjectPage
     * @param request
     * @return
     */
    @Override
    public Page<BisheProjectVO> getBisheProjectVOPage(Page<BisheProject> bisheProjectPage, HttpServletRequest request) {
        List<BisheProject> bisheProjectList = bisheProjectPage.getRecords();
        Page<BisheProjectVO> bisheProjectVOPage = new Page<>(bisheProjectPage.getCurrent(), bisheProjectPage.getSize(), bisheProjectPage.getTotal());
        if (CollUtil.isEmpty(bisheProjectList)) {
            return bisheProjectVOPage;
        }
        // 对象列表 => 封装对象列表
        List<BisheProjectVO> bisheProjectVOList = bisheProjectList.stream().map(bisheProject -> {
            return BisheProjectVO.objToVo(bisheProject);
        }).collect(Collectors.toList());

        // 可以根据需要为封装对象补充值，不需要的内容可以删除
        // region 可选
        // 1. 关联查询用户信息
        Set<Long> userIdSet = bisheProjectList.stream().map(BisheProject::getUserId).collect(Collectors.toSet());
        Map<Long, List<User>> userIdUserListMap = userService.listByIds(userIdSet).stream()
                .collect(Collectors.groupingBy(User::getId));

        // 填充信息
        bisheProjectVOList.forEach(bisheProjectVO -> {
            Long userId = bisheProjectVO.getUserId();
            User user = null;
            if (userIdUserListMap.containsKey(userId)) {
                user = userIdUserListMap.get(userId).get(0);
            }
            bisheProjectVO.setUser(userService.getUserVO(user));
        });
        // endregion

        bisheProjectVOPage.setRecords(bisheProjectVOList);
        return bisheProjectVOPage;
    }

    /**
     * 分按日期分组查询毕设项目新增数量
     *
     * @param beginDate 开始时间
     * @param endDate   结束时间
     * @return
     */
    @Override
    public List<DataGroupByDateDTO> countByDay(Date beginDate, Date endDate) {
        QueryWrapper<BisheProject> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("DATE_FORMAT(create_time, '%Y-%m-%d') AS day", "COUNT(1) AS num");
        queryWrapper.ge("create_time", beginDate);
        queryWrapper.le("create_time", endDate);
        queryWrapper.groupBy("day");
        queryWrapper.orderByAsc("day");
        // 执行查询
        List<Map<String, Object>> results = this.baseMapper.selectMaps(queryWrapper);
        // 映射到 DataGroupByDateDTO
        return results.stream().map(result -> {
            DataGroupByDateDTO dto = new DataGroupByDateDTO();
            dto.setDay(DateUtils.parse(result.get("day").toString(), DateUtils.FMT_YMD));
            dto.setNum(((Number) result.get("num")).intValue()); // 修改为Integer类型
            return dto;
        }).collect(Collectors.toList());
    }

    @Override
    public Page<BisheProject> getBisheProjectPage(Page<BisheProject> bisheProjectPage) {
        List<BisheProject> bisheProjectList = bisheProjectPage.getRecords();
        Page<BisheProject> bisheProjectPage2 = new Page<>(bisheProjectPage.getCurrent(), bisheProjectPage.getSize(), bisheProjectPage.getTotal());
        if (CollUtil.isEmpty(bisheProjectList)) {
            return bisheProjectPage2;
        }
        // 对象列表 => 封装对象列表
        List<BisheProject> bisheProjectList2 = bisheProjectList.stream().map(bisheProject -> {
            bisheProject.setTagList(JSONUtil.toList(bisheProject.getTags(), String.class));
            return bisheProject;
        }).collect(Collectors.toList());

        //其它操作


        bisheProjectPage2.setRecords(bisheProjectList2);
        return bisheProjectPage2;
    }

    @Override
    public long doClick(Long bisheProjectId) {
        // 判断实体是否存在，根据类别获取实体
        BisheProject bisheProject = this.getById(bisheProjectId);
        if (bisheProject == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        //浏览数+1
        this.update().eq("id", bisheProjectId).setSql("click_num = click_num + 1").update();
        return bisheProject.getClickNum() + 1;
    }

    @Override
    public Long getClickNumTotalCount() {

        //构建查询条件,只查询click_num字段
        QueryWrapper<BisheProject> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("click_num");
        return this.list(queryWrapper).stream().map(BisheProject::getClickNum).reduce(0L, (old, next) -> old + next);

    }

    @Override
    public List<WordCloud> getBisheProjectTagWordCloud() {

        //1. 获取所有的毕设项目信息
        //1.1 构造查询条件
        QueryWrapper<BisheProject> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("tags");
        //1.2 查询Tags
        List<String> tagStrList = this.list(queryWrapper).stream().map(BisheProject::getTags).collect(Collectors.toList());

        //2. 将Tags转换为TagList
        List<List<String>> tagListList = tagStrList.stream()
                .filter(StringUtils::isNotBlank)
                .map(str -> JSONUtil.toList(str, String.class))
                .collect(Collectors.toList());

        //3. 平铺Tag并统计频率
        Map<String, Long> tagCountMap = tagListList.stream()
                .flatMap(List::stream)
                .filter(StringUtils::isNotBlank)
                .collect(Collectors.groupingBy(tag -> tag, Collectors.counting()));

        //4. 构造WordCloud
        List<WordCloud> wordCloudList = tagCountMap.entrySet().stream()
                .map(entry -> {
                    WordCloud wordCloud = new WordCloud();
                    wordCloud.setText(entry.getKey());
                    wordCloud.setName(entry.getKey());
                    wordCloud.setValue(entry.getValue().intValue());
                    return wordCloud;
                })
                .sorted((a, b) -> b.getValue() - a.getValue()) // 按出现频率降序排序
                .collect(Collectors.toList());

        return wordCloudList;
    }

    @Override
    public BisheProjectStatisticsDTO getBisheStatistics() {

        BisheProjectStatisticsDTO bisheStatisticsDTO = new BisheProjectStatisticsDTO();

        //1. 点击量前15的项目
        List<BisheProjectClickDTO> top15BisheProjectsByClickNum = getTop15ProjectsByClickNum();
        bisheStatisticsDTO.setTop15BisheProjectsByClickNum(top15BisheProjectsByClickNum);


        //2. 销售量前7的项目
        List<ChartDataItem> top7BisheProjectsByAmount = getTop7BisheProjectsByAmount();
        bisheStatisticsDTO.setTop7BisheProjectsByAmount(top7BisheProjectsByAmount);


        return bisheStatisticsDTO;
    }


    /**
     * 获取销售量前7的项目
     *
     * @return 销售量前7的项目列表
     */
    private List<ChartDataItem> getTop7BisheProjectsByAmount() {
        //1. 根据 type => 查询订单信息(targetId,amount)
        String type = OrderInfoTypeEnum.PROJECT.getValue();
        Integer status = OrderInfoStatusEnum.HAS_PAY.getValue();
        QueryWrapper<OrderInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("target_id", "amount");
        queryWrapper.eq("type", type);
        queryWrapper.eq("status", status); // 建议添加已支付状态过滤
        List<OrderInfo> orderInfoList = orderInfoMapper.selectList(queryWrapper);

        // 如果没有订单数据，直接返回空列表
        if (CollUtil.isEmpty(orderInfoList)) {
            return new ArrayList<>();
        }

        //2. 根据 targetId 进行分类
        Map<Long, List<OrderInfo>> targetIdOrderInfoListMap = orderInfoList.stream()
                .collect(Collectors.groupingBy(OrderInfo::getTargetId));

        //3. 查询对应的bisheProject的name
        Set<Long> targetIdSet = orderInfoList.stream().map(OrderInfo::getTargetId).collect(Collectors.toSet());
        List<BisheProject> bisheProjectList = this.listByIds(targetIdSet);

        //4. 对象映射: x为bisheProject的name, y为amount
        List<ChartDataItem> result = bisheProjectList
                .stream()
                .map(bisheProject -> {
                    Long targetId = bisheProject.getId();
                    if (targetIdOrderInfoListMap.containsKey(targetId)) {
                        Integer amount = targetIdOrderInfoListMap.get(targetId).stream()
                                .map(OrderInfo::getAmount)
                                .reduce(0, Integer::sum);
                        ChartDataItem chartDataItem = new ChartDataItem();
                        chartDataItem.setX(bisheProject.getTitle());
                        chartDataItem.setY(amount);
                        return chartDataItem;
                    }
                    return null;
                })
                .filter(Objects::nonNull) // 过滤掉null值
                .sorted((a, b) -> b.getY() - a.getY()) // 按销售额降序排序
                .limit(7) // 只取前7个
                .collect(Collectors.toList());

        //5. 返回
        return result;
    }


    /**
     * 获取点击量前15的项目
     *
     * @return 点击量前15的项目列表
     */
    private List<BisheProjectClickDTO> getTop15ProjectsByClickNum() {
        // 构建查询条件
        QueryWrapper<BisheProject> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("id", "title", "click_num");
        queryWrapper.orderByDesc("click_num");
        queryWrapper.last("LIMIT 15"); // 限制只查询前15条记录

        // 执行查询
        List<BisheProject> projectList = this.list(queryWrapper);

        // 转换为DTO
        List<BisheProjectClickDTO> projectClickDTOList = projectList.stream()
                .map(project -> {
                    BisheProjectClickDTO dto = new BisheProjectClickDTO();
                    dto.setName(project.getTitle());
                    dto.setClickNum(project.getClickNum().intValue()); // 将Long转为Integer
                    return dto;
                })
                .collect(Collectors.toList());

        return projectClickDTOList;
    }


}
